package com.ruoyi.eqmonitor.service.impl;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import com.baomidou.lock.executor.RedisTemplateLockExecutor;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.eqmonitor.dispose.dtos.JudgeOverproofVo;
import com.ruoyi.eqmonitor.dispose.service.ExteriorSiteMonitorDataService;
import com.ruoyi.eqmonitor.domain.*;
import com.ruoyi.eqmonitor.dtos.*;
import com.ruoyi.eqmonitor.mapper.OptDeviceAlarmMapper;
import com.ruoyi.eqmonitor.mapper.OptDeviceMapper;
import com.ruoyi.eqmonitor.service.*;
import com.ruoyi.eqmonitor.smdtv.mapper.SmregisterMapper;
import com.ruoyi.eqmonitor.smdtv.service.ISmdtv9Service;
import com.ruoyi.eqmonitor.utils.Constant;
import com.ruoyi.eqmonitor.vo.BszsVo;
import com.ruoyi.eqmonitor.vo.CsyzVo;
import com.ruoyi.eqmonitor.vo.ReportCVo;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;


/**
 * 【请填写功能名称】Service业务层处理
 *
 * @author ruoyi
 * @date 2022-11-25
 */
@Slf4j
@Service
public class OptDeviceAlarmServiceImpl extends ServiceImpl<OptDeviceAlarmMapper, OptDeviceAlarm> implements IOptDeviceAlarmService {
    @Autowired
    private LockTemplate lockTemplate;
    @Autowired
    private IPipeService iPipeService;

    @Autowired
    private IOptAreaSettingService optAreaSettingService;

    @Autowired
    private ISmdtv9Service ISmdtv9Service;
    @Autowired
    private OptSewageRenovateService optSewageRenovateService;
    @Autowired
    private OptInterceptingWellRenovateService optInterceptingWellRenovateService;
    @Autowired
    private OptDeviceMapper optDeviceMapper;
    @Autowired
    private ExteriorSiteMonitorDataService exteriorSiteMonitorDataService;

    @Resource
    private SmregisterMapper smregisterMapper;

    @Override
    public OptDeviceAlarm selectOptDeviceAlarmById(Long id){
        return baseMapper.selectOptDeviceAlarmById(id);
    }

    @Override
    public List<OptDeviceAlarm> selectOptDeviceAlarmList(AlarmSearchInput optDeviceAlarm){
        return baseMapper.selectOptDeviceAlarmList(optDeviceAlarm);
    }

    @Override
    public List<OptDeviceAlarmDto> listAndDispatch(AlarmSearchInput optDeviceAlarm) {
        return injectDispatchInfo(baseMapper.listVo(optDeviceAlarm));
//        return baseMapper.listAndDispatch(optDeviceAlarm);
    }

    @Override
    public List<OptDeviceAlarmDto> newestList(AlarmSearchInput dto) throws ParseException {
        Integer state = dto.getState();
        Calendar calendar = Calendar.getInstance();
        String startTime = null;
        //取当天数据
        if (state == 0){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            startTime = sdf.format(calendar.getTime());
            dto.setStartTime(sdf.parse(startTime));
        }else if (state == 1){ //取近三天数据
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            calendar.add(Calendar.DATE, -3);
            startTime = sdf.format(calendar.getTime()) ;
            dto.setStartTime(sdf.parse(startTime));
        }
        List<OptDeviceAlarmDto> list = baseMapper.listAndDispatch(dto);
        //当天没有数据则查询前一天数据
//        if (list.size() == 0 && dto.getState() == 0){
//            Calendar calendar1 = Calendar.getInstance();
//            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            calendar1.add(Calendar.DATE, -1);
//            startTime = sdf.format(calendar1.getTime());
//            dto.setStartTime(sdf.parse(startTime));
//            list = baseMapper.listAndDispatch(dto);
//        }
        for (OptDeviceAlarmDto optDeviceAlarmDto: list){
            String deviceCode = optDeviceAlarmDto.getDeviceCode();
            Integer alarmPhenomenon = dto.getAlarmPhenomenon();
            optDeviceAlarmDto.setAlarmCount(baseMapper.getDayAlarmCount(deviceCode,startTime,alarmPhenomenon));
        }

        return list;
    }
    /**
     * 运维管理使用 -- 按时间周期搜索
     */
    @Override
    public List<OptDeviceAlarmDto> deviceListAndDispatch(AlarmSearchInput optDeviceAlarm) {
        return injectDispatchInfo(baseMapper.deviceList(optDeviceAlarm));
//        return baseMapper.deviceListAndDispatch(optDeviceAlarm);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePersistentStatusToFalse(String deviceCode, String alarmType, String alarmPhenomenon, String alarmCode) {
        Assert.notNull(deviceCode, "设备编码不能为空");
        Assert.notNull(alarmType, "报警类型不能为空");
        Assert.notNull(alarmPhenomenon, "报警现象不能为空");
        String lockKey = StrUtil.format("do_{}-{}-{}-{}", deviceCode, alarmCode, alarmType, alarmPhenomenon);
        // 获取锁
        final LockInfo lockInfo = lockTemplate.lock(lockKey, 30000L, 5000L, RedisTemplateLockExecutor.class);
        if (null == lockInfo) {
            log.error("业务处理中, 请稍后再试");
        }
        LambdaUpdateWrapper<OptDeviceAlarm> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(OptDeviceAlarm::getDeviceCode, deviceCode);
        updateWrapper.eq(OptDeviceAlarm::getAlarmType, alarmType);
        updateWrapper.eq(OptDeviceAlarm::getAlarmPhenomenon, alarmPhenomenon);
        updateWrapper.eq(ObjectUtil.isNotNull(alarmCode), OptDeviceAlarm::getAlarmCode, alarmCode);
        updateWrapper.set(OptDeviceAlarm::getPersistentStatus, Constant.FALSE);
        baseMapper.update(null, updateWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doSaveAlarm(OptDeviceAlarm alarm) {
        String lockKey = StrUtil.format("do_{}-{}-{}-{}", alarm.getDeviceCode(), alarm.getAlarmCode(), alarm.getAlarmType(), alarm.getAlarmPhenomenon());
        // 获取锁
        final LockInfo lockInfo = lockTemplate.lock(lockKey, 30000L, 5000L, RedisTemplateLockExecutor.class);
        if (null == lockInfo) {
            log.error("业务处理中, 请稍后再试");
        }
        // 获取锁成功，处理业务
        try {
            String deviceCode = alarm.getDeviceCode();
            Assert.notNull(deviceCode, "设备编码不存在");
//        Integer alarmType = alarm.getAlarmType();
//        Integer alarmPhenomenon = alarm.getAlarmPhenomenon();
//        String alarmCode = StrUtil.emptyToDefault(alarm.getAlarmCode(), "-");
//        String lockKey = StrUtil.format("{}-{}-{}-{}", deviceCode, alarmType, alarmPhenomenon, alarmCode);
//        log.info("当前执行: {}", lockKey);
            // 数据已经超限则查询是否存在对应的报警记录
            LambdaQueryWrapper<OptDeviceAlarm> wrapper = new LambdaQueryWrapper<>();
            // 查询记录必须为未清除的记录 并且设备编码,监测指标,报警类型为传入值 并且是持续报警
            wrapper.ne(OptDeviceAlarm::getConfirmAlarm, Constant.ConfirmAlarmType.CLEARED.getValue())
                    .eq(OptDeviceAlarm::getPersistentStatus, Constant.TRUE)
                    .eq(OptDeviceAlarm::getDeviceCode, alarm.getDeviceCode())
                    .eq(OptDeviceAlarm::getAlarmType, alarm.getAlarmType())
                    .eq(OptDeviceAlarm::getAlarmPhenomenon, alarm.getAlarmPhenomenon())
                    .eq(StrUtil.isNotBlank(alarm.getAlarmCode()), OptDeviceAlarm::getAlarmCode, alarm.getAlarmCode());
            wrapper.last("LIMIT 1");
            OptDeviceAlarm one = getOne(wrapper);
            // 新增或修改
            if (ObjectUtil.isNotNull(one)) {
//            one.setDeviceCode(null);
                one.setDeviceName(alarm.getDeviceName());
                one.setSiteName(alarm.getSiteName());
                one.setDeviceType(alarm.getDeviceType());
                one.setInstallTime(alarm.getInstallTime());
                one.setAbx(alarm.getAbx());
                one.setAby(alarm.getAby());
//            one.setAlarmCode(null);
                one.setAlarmCodeValue(alarm.getAlarmCodeValue());
                one.setAlarmCount(one.getAlarmCount() == null ? 2 : (one.getAlarmCount() + 1));
//            one.setConfirmAlarm(null);
//            one.setProcessStatus(null);
//            one.setConfirmUserid(null);
//            one.setConfirmUsername(null);
//            one.setReadStatus(null);
//            one.setDisUserid(null);
//            one.setDisUsername(null);
//            one.setReceiveUserid(null);
//            one.setProcessDesc(null);
//            one.setAlarmType(null);
//            one.setAlarmPhenomenon(null);
//            one.setAlarmTime(null);
                Date lastAlarmTime = DateUtil.compare(one.getLastAlarmTime(), alarm.getLastAlarmTime()) < 0 ?
                        alarm.getLastAlarmTime() : one.getLastAlarmTime();
                one.setLastAlarmTime(lastAlarmTime);
                updateById(one);
            } else {
                Assert.notBlank(alarm.getDeviceCode(), "设备编码不允许为空");
                Assert.notNull(alarm.getAlarmType(), "报警类型不允许为空");
                Assert.notNull(alarm.getAlarmPhenomenon(), "报警现象不允许为空");
                Assert.notNull(alarm.getAlarmTime(), "报警时间不允许为空");
                alarm.setAlarmCount(1);
                alarm.setLastAlarmTime(alarm.getLastAlarmTime());
                if (alarm.getAlarmPhenomenon().equals("12")) {
                    alarm.setDescribed("溢流井晴天有水流出");
                }
                /*if (alarm.getDeviceType().equals(Constant.EquipmentType.SR500_L_Y0_LDN.getCode()) &&
                        alarm.getAlarmCode().equals(Constant.MonitorInfo.M_0x0528.getCode()) &&
                        alarm.getAlarmPhenomenon().equals("6")) {
                    alarm.setDescribed("水质超标排放");
                }*/
//                one = alarm;
                save(alarm);
            }
            //记录日志
            log.info("信息:{}", one);
        } finally {
            //释放锁
            lockTemplate.releaseLock(lockInfo);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void updatePersistentStatus(OptDeviceAlarm alarm) {
        LambdaUpdateWrapper<OptDeviceAlarm> wrapper = new LambdaUpdateWrapper<>();
        // 查询记录必须为未清除的记录 并且设备编码和监测数据为传入值
        wrapper.ne(OptDeviceAlarm::getConfirmAlarm, Constant.ConfirmAlarmType.CLEARED.getValue())
                .eq(OptDeviceAlarm::getDeviceCode, alarm.getDeviceCode())
                .eq(OptDeviceAlarm::getAlarmType, alarm.getAlarmType())
                .eq(OptDeviceAlarm::getAlarmPhenomenon, alarm.getAlarmPhenomenon())
                .eq(ObjectUtil.isNotNull(alarm.getAlarmCode()), OptDeviceAlarm::getAlarmCode, alarm.getAlarmCode())
                // 修改为不持续报警
                .set(OptDeviceAlarm::getPersistentStatus, Constant.FALSE);
        update(wrapper);
    }

    /**
     * 创建报警实体
     * @param device 设备对象
     * @param config 阈值配置对象
     * @param monitorData 采集数据值
     */
    @Override
    public OptDeviceAlarm buildAlarmEntity(OptDeviceDto device,
                                           OptDeviceMonitorConfig config,
                                           Double monitorData,
                                           Date alarmTime) {
        OptDeviceAlarm optDeviceAlarm = new OptDeviceAlarm();
        optDeviceAlarm.setDeviceName(device.getDeviceName());
        optDeviceAlarm.setDeviceCode(device.getDeviceCode());
        optDeviceAlarm.setSiteName(device.getSiteName());
        optDeviceAlarm.setDeviceType(device.getDeviceType());
        optDeviceAlarm.setInstallTime(device.getInstallTime());
        optDeviceAlarm.setAbx(device.getAbx());
        optDeviceAlarm.setAby(device.getAby());
        optDeviceAlarm.setAlarmCode(config.getAlarmCode());
        optDeviceAlarm.setAlarmCodeValue(monitorData);
        optDeviceAlarm.setAlarmType(config.getAlarmType());
        optDeviceAlarm.setAlarmPhenomenon(config.getAlarmPhenomenon());
        optDeviceAlarm.setConfirmAlarm(Constant.ConfirmAlarmType.UNCONFIRMED.getValue());
        optDeviceAlarm.setAlarmCount(1);
        optDeviceAlarm.setAlarmTime(alarmTime);
        optDeviceAlarm.setLastAlarmTime(alarmTime);
        optDeviceAlarm.setConfigAlarmValue(config.getAlarmValue());
        optDeviceAlarm.setConfigFloorLimit(config.getFloorLimit());
        optDeviceAlarm.setConfigUpperLimit(config.getUpperLimit());
        optDeviceAlarm.setPersistentStatus(Constant.TRUE);
        return optDeviceAlarm;
    }

    @Override
    public List<OptDeviceAlarmDto> selectOptDeviceAlarmClogList(OptDeviceAlarmDto dto) {
        return injectDispatchInfo(baseMapper.selectOptDeviceAlarmClogList(dto));
//        return baseMapper.selectOptDeviceAlarmClogList(dto);
    }

    @Override
    public OptDeviceAlarmDto selectOptDeviceAlarmClogInfo(Long id) {
        OptDeviceAlarmDto optDeviceAlarmDto = baseMapper.selectOptDeviceAlarmClogInfo(id);
        if (optDeviceAlarmDto != null && optDeviceAlarmDto.getPipeWtdh() != null) {
            optDeviceAlarmDto.setPointInfo(iPipeService.getPointByWtdh(optDeviceAlarmDto.getPipeType(), optDeviceAlarmDto.getPipeWtdh()));
            optDeviceAlarmDto.setLineInfo(iPipeService.getLineByPointWtdh(optDeviceAlarmDto.getPipeType(), optDeviceAlarmDto.getPipeWtdh()));
        }
        return optDeviceAlarmDto;
    }

    @Override
    public Long mySelectCount(List<String> deviceTypes,List<String> areaCodes,String areaName) {
        return baseMapper.mySelectCount(deviceTypes,areaCodes,areaName);
    }

    @Override
    public List<Map<String, Object>> quantityStatistics(OptDeviceAlarmDto dto) {
        return baseMapper.quantityStatistics(dto);
    }

    @Override
    public boolean updateConfirmAlarmToClear(Long alarmId) {
        if (ObjectUtil.isNull(alarmId)) return false;
        LambdaUpdateWrapper<OptDeviceAlarm> wrapper = Wrappers.lambdaUpdate();
        // 清除
        wrapper.set(OptDeviceAlarm::getConfirmAlarm, Constant.ConfirmAlarmType.CLEARED.getValue());
        // 不持续报警
        wrapper.set(OptDeviceAlarm::getPersistentStatus, Constant.FALSE);
        wrapper.eq(OptDeviceAlarm::getId, alarmId);
        return update(wrapper);
    }

    @Override
    public boolean updateConfirmAlarmToInDisposal(Long alarmId) {
        if (ObjectUtil.isNull(alarmId)) return false;
        LambdaUpdateWrapper<OptDeviceAlarm> wrapper = Wrappers.lambdaUpdate();
        wrapper.set(OptDeviceAlarm::getConfirmAlarm, Constant.ConfirmAlarmType.IN_DISPOSAL.getValue());
        wrapper.eq(OptDeviceAlarm::getId, alarmId);
        return update(wrapper);
    }

    @Override
    public OptDeviceAlarmDto minSewageAlarmByDeviceCode(String deviceCode, String alarmPhenomenon) {
        return baseMapper.minSewageAlarmByDeviceCode(deviceCode, alarmPhenomenon);
    }

    @Override
    public OptDeviceAlarmDto maxSewageAlarmByDeviceCode(String deviceCode, String alarmPhenomenon) {
        return baseMapper.maxSewageAlarmByDeviceCode(deviceCode, alarmPhenomenon);
    }

    @Override
    public List<CsyzVo> selectCsyzBackstage(CsyzVo query){
        Date beginTime = query.getBeginTime();
        Date endTime = query.getEndTime();
        String beginTimeString = null;
        String endTimeString = null;
        if (beginTime != null){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            beginTimeString = sdf.format(beginTime);
            endTimeString = sdf.format(endTime);
        }
        List<CsyzVo> list = baseMapper.selectCsyzBackstage(query.getAreaName(),beginTimeString,endTimeString);
        for (CsyzVo dto : list){
            //管网健康
            BigDecimal health = this.calculate(dto.getFlaw(), dto.getSumKM());
            dto.setHealth(health.toString());
            //管网於堵
            BigDecimal blockageZ = this.calculate(dto.getBlockage(), dto.getBlockageEquipment());
            dto.setBlockageZ(blockageZ.toString());
            //入流入渗
            BigDecimal inflowAndInfiltrationZ = this.calculate(dto.getInflowAndInfiltration(), dto.getIIEquipment());
            dto.setInflowAndInfiltrationZ(inflowAndInfiltrationZ.toString());
            //管网负荷
            BigDecimal load = this.calculate(dto.getSpillOver(), dto.getSumKM());
            dto.setLoad(load.toString());
            //管网巡检
            BigDecimal polling = this.calculate2(dto.getIncidentOver(),dto.getIncident());
            dto.setPolling(polling.toString());
            //加入合计
            dto.setTotal((health
                    .add(blockageZ)
                    .add(inflowAndInfiltrationZ)
                    .add(load)
                    .add(polling)).divide(new BigDecimal(5),2,BigDecimal.ROUND_HALF_UP).toString());
        }
        return list;
    }

    @Override
    public List<BszsVo> selectBSZSBackstage(BszsVo query) {
        Date beginTime = query.getBeginTime();
        Date endTime = query.getEndTime();
        String beginTimeString = null;
        String endTimeString = null;
        if (beginTime != null){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            beginTimeString = sdf.format(beginTime);
            endTimeString = sdf.format(endTime);
        }
        List<JudgeOverproofVo> waterQualityBackstage = exteriorSiteMonitorDataService.judgeOverproof(query.getAreaName(), beginTimeString, endTimeString);
        List<BszsVo> list = baseMapper.selectBSZSBackstage(query.getAreaName(),beginTimeString,endTimeString,
                smregisterMapper.getTableNameByDatasetName(Constant.Smregister.SMDTV_9.getName()));
        for (BszsVo dto : list){
            String areaName = dto.getAreaName();
            //断面水质达标率
            Long sum = 0L;
            for (JudgeOverproofVo judgeOverproofVo : waterQualityBackstage){
                if (areaName.equals(judgeOverproofVo.getAreaName())){
                    //断面达标数
                    sum = judgeOverproofVo.getSum();
                    break;
                }
            }
            //加入7个断面
            if (areaName.equals("峰江街道") || areaName.equals("螺洋街道") ||areaName.equals("路桥街道") ||areaName.equals("桐屿街道") ||areaName.equals("蓬街镇")){
                sum += 1;
            }else if (areaName.equals("金清镇")){
                sum += 2;
            }
            dto.setMicrostationOver(sum);
            BigDecimal waterQualityZ = this.calculate2(sum, dto.getMicrostationSum());
            dto.setWaterQualityZ(waterQualityZ.toString());
            //整治完成率
            BigDecimal interceptingWellZA = this.calculate2(dto.getInterceptingWellRenovate(), dto.getInterceptingWellSum());
            dto.setInterceptingWellZA(interceptingWellZA.toString());
            //溢流井氨氮报警率
            BigDecimal interceptingWellZB = this.calculate(dto.getInterceptingWell(), dto.getInterceptingWellDevice());
            dto.setInterceptingWellZB(interceptingWellZB.toString());
            //溢流井整治情况
            BigDecimal interceptingWellZ = (interceptingWellZA.multiply(new BigDecimal("0.8"))).add(interceptingWellZB.multiply(new BigDecimal("0.2"))).divide(new BigDecimal(1),2, BigDecimal.ROUND_HALF_UP);
            dto.setInterceptingWellZ(interceptingWellZ.toString());
            //排污口整治情况
            BigDecimal drainOutletZ = this.calculate2(dto.getDrainOutletRenovate(), dto.getDrainOutletSum());
            dto.setDrainOutletZ(drainOutletZ.toString());
            //水质报警情况
            BigDecimal waterQualityOverZ = this.calculate(dto.getWaterQuality(),dto.getWaterQualityDevice());
            dto.setWaterQualityOverZ(waterQualityOverZ.toString());
            //水质事件处理情况
            BigDecimal waterQualityIncidentZ = this.calculate2(dto.getWaterQualityOver(),dto.getWaterQualitySum());
            dto.setWaterQualityIncidentZ(waterQualityIncidentZ.toString());
            //加入合计
            dto.setTotal((waterQualityZ
                    .add(interceptingWellZ)
                    .add(drainOutletZ)
                    .add(waterQualityOverZ)
                    .add(waterQualityIncidentZ)).divide(new BigDecimal(5),2,BigDecimal.ROUND_HALF_UP).toString());
        }
        return list;
    }

    @Override
    public Map<String, Object> selectYWSZBJ() {
        Map<String, Object> map = new HashMap<>();
        AlarmSearchInput optDeviceAlarm = new AlarmSearchInput();

        //液位高度
        optDeviceAlarm.setAlarmCode(Constant.MonitorInfo.M_0x05D1.getCode());
        List<OptDeviceAlarmDto> yw = baseMapper.listAndDispatch(optDeviceAlarm);
        //水质
        List<String> list = new ArrayList<>();
        list.add(Constant.MonitorInfo.M_0x0527.getCode());//COD
        list.add(Constant.MonitorInfo.M_0x0523.getCode());//电导率
        list.add(Constant.MonitorInfo.M_0x0528.getCode());//氨氮
        optDeviceAlarm.setAlarmCode(null);
        optDeviceAlarm.setAlarmCodes(list);
        List<OptDeviceAlarmDto> sz = baseMapper.listAndDispatch(optDeviceAlarm);

        map.put("液位",yw);
        map.put("水质",sz);
        return map;
    }

    @Override
    public List<OptDeviceAlarmDto> selectRiverwayAlarm(RiverwayAlarmDto dto) {
        List<String> searchValues = dto.getSearchValues();
        List<String> list = new ArrayList<>();
        list.add(Constant.EquipmentType.SE200_L_Y0.getCode());
        //list.add(Constant.EquipmentType.SR500_L_Y0_LDN.getCode());
        return baseMapper.selectRiverwayAlarm(DateUtils.toString(dto.getBeginTimeDate()),
                DateUtils.toString(dto.getEndTimeDate()),null, searchValues, list);
    }

    @Override
    public List<OptDevice> backstageDeviceCall(Integer state, BszsVo query) {
        List<String> deviceTypeList = new ArrayList<>();
        List<Integer> alarmPhenomenonList = new ArrayList<>();
        List<Integer> confirmAlarmList = new ArrayList<>();
        switch (state){
            case 1://溢流井报警设备
                //deviceTypeList.add(Constant.EquipmentType.SR500_L_Y0_LDN.getCode());
                confirmAlarmList.add(0);
                confirmAlarmList.add(1);
                break;
            case 2://水质报警设备 或 管网入流入渗设备
                //deviceTypeList.add(Constant.EquipmentType.SR500_L_Y0_LDN.getCode());
                //deviceTypeList.add(Constant.EquipmentType.SR500_L_Y0_SNY.getCode());
                //deviceTypeList.add(Constant.EquipmentType.SR500_L_Y0_STE.getCode());
                //deviceTypeList.add(Constant.EquipmentType.SR500_L_Y0_SYT.getCode());
                alarmPhenomenonList.add(3);
                alarmPhenomenonList.add(5);
                alarmPhenomenonList.add(6);
                confirmAlarmList.add(0);
                confirmAlarmList.add(1);
                break;
            case 3://管网淤堵报警设备
                deviceTypeList.add(Constant.EquipmentType.SY800_L_Y0.getCode());
                //deviceTypeList.add(Constant.EquipmentType.SR500_L_Y0_SYT.getCode());
                //deviceTypeList.add(Constant.EquipmentType.SR500_L_Y0_STE.getCode());
                alarmPhenomenonList.add(0);
                confirmAlarmList.add(0);
                confirmAlarmList.add(1);
                break;
            //管网缺陷点设备
            case 4:
                deviceTypeList.add(Constant.EquipmentType.SY800_L_Y0.getCode());
                alarmPhenomenonList.add(0);
                alarmPhenomenonList.add(2);
                confirmAlarmList.add(0);
                confirmAlarmList.add(1);
                break;

        }

        return baseMapper.backstageDeviceCall(query,deviceTypeList,alarmPhenomenonList,confirmAlarmList);
    }

    @Override
    public ReportCVo report(WordReportDto dto) throws ParseException {
        int state = dto.getState();
        ReportCVo vo = new ReportCVo();
        if (state == 0 || state == 1) {
            //本月排名
            int bszs1 = bszsQueryData(dto.getAreaName(), dto.getBeginDate(), dto.getEndDate());
            vo.setC1(bszs1 + "");
            int csyz1 = csyzQueryData(dto.getAreaName(), dto.getBeginDate(), dto.getEndDate());
            vo.setC3(csyz1 + "");
            if (state == 0) {
                //上月排名
                int bszs2 = bszsQueryData(dto.getAreaName(), dto.getLastBeginDate(), dto.getLastEndDate());
                vo.setLastC1(bszs2 + "");
                if (bszs1 - bszs2 > 0) {
                    vo.setC2("上升" + (bszs1 - bszs2) + "名");
                } else if (bszs1 - bszs2 < 0) {
                    vo.setC2("下降" + (bszs2 - bszs1) + "名");
                } else {
                    vo.setC2("排名无变化");
                }
                int csyz2 = csyzQueryData(dto.getAreaName(), dto.getLastBeginDate(), dto.getLastEndDate());
                vo.setLastC3(csyz2 + "");
                if (csyz1 - csyz2 > 0) {
                    vo.setC4("上升" + (csyz1 - csyz2) + "名");
                } else if (csyz1 - csyz2 < 0) {
                    vo.setC4("下降" + (csyz2 - csyz1) + "名");
                } else {
                    vo.setC4("排名无变化");
                }
            } else {
                //去年同月排名
                int bszs3 = bszsQueryData(dto.getAreaName(), dto.getLastYearBeginDate(), dto.getLastYearEndDate());
                if (bszs1 - bszs3 > 0) {
                    vo.setC5("上升" + (bszs1 - bszs3) + "名");
                } else if (bszs1 - bszs3 < 0) {
                    vo.setC5("下降" + (bszs3 - bszs1) + "名");
                } else {
                    vo.setC5("排名无变化");
                }
                int csyz3 = csyzQueryData(dto.getAreaName(), dto.getLastYearBeginDate(), dto.getLastYearEndDate());
                if (csyz1 - csyz3 > 0) {
                    vo.setC6("上升" + (csyz1 - csyz3) + "名");
                } else if (csyz1 - csyz3 < 0) {
                    vo.setC6("下降" + (csyz3 - csyz1) + "名");
                } else {
                    vo.setC6("排名无变化");
                }
            }
        } else {
            //本年排名
            int bszs4 = bszsQueryData(dto.getAreaName(), dto.getYearBeginDate(), dto.getYearEndDate());
            vo.setC7(bszs4 + "");
            int csyz4 = csyzQueryData(dto.getAreaName(), dto.getYearBeginDate(), dto.getYearEndDate());
            vo.setC9(csyz4 + "");
            //去年排名
            int bszs5 = bszsQueryData(dto.getAreaName(), dto.getYearBeginDate(), dto.getYearEndDate());
            if (bszs4 - bszs5 > 0) {
                vo.setC8("上升" + (bszs4 - bszs5) + "名");
            } else if (bszs4 - bszs5 < 0) {
                vo.setC8("下降" + (bszs5 - bszs4) + "名");
            } else {
                vo.setC8("排名无变化");
            }
            int csyz5 = csyzQueryData(dto.getAreaName(), dto.getYearBeginDate(), dto.getYearEndDate());
            if (csyz4 - csyz5 > 0) {
                vo.setC10("上升" + (csyz4 - csyz5) + "名");
            } else if (csyz4 - csyz5 < 0) {
                vo.setC10("下降" + (csyz5 - csyz4) + "名");
            } else {
                vo.setC10("排名无变化");
            }
        }

//        vo.setC11();
//        vo.setC12();

        return vo;
    }

    @Override
    public int countAlarm(String siteId, LocalDateTime startTime, LocalDateTime endTime) {
        return baseMapper.countAlarmCount(siteId,  startTime, endTime);
    }

    /**
     * 计算(1-molecule/denominator)*100
     */
    private BigDecimal calculate(Object molecule, Object denominator) {
        if (!denominator.toString().equals("0")) {
            return (new BigDecimal(1).subtract(new BigDecimal(molecule.toString()).divide(new BigDecimal(denominator.toString()), 2, BigDecimal.ROUND_HALF_UP))).multiply(new BigDecimal(100));
        } else {
            return new BigDecimal("100.00");
        }
    }

    /**
     * 计算(molecule/denominator)*100
     */
    private BigDecimal calculate2(Object molecule, Object denominator) {
        if (!denominator.toString().equals("0")) {
            return (new BigDecimal(molecule.toString()).divide(new BigDecimal(denominator.toString()), 2, BigDecimal.ROUND_HALF_UP)).multiply(new BigDecimal(100));
        } else {
            return new BigDecimal("100.00");
        }
    }

    //碧水指数
    private int bszsQueryData(String areaName,String begin,String end) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        BszsVo bszsDto = new BszsVo();
        bszsDto.setBeginTime(sdf.parse(begin));
        bszsDto.setEndTime(sdf.parse(end));
        List<BszsVo> bszsVO = this.selectBSZSBackstage(bszsDto);
        List<BszsVo> collect = bszsVO.stream().sorted(Comparator.comparing(BszsVo::getTotal, Comparator.reverseOrder())).collect(Collectors.toList());
        for (int i=0; i<collect.size(); i++){
            BszsVo dto = collect.get(i);
            if (dto.getAreaName().equals(areaName)){
                return i;
            }
        }
        return 1;
      }

    //畅水因子
    private int csyzQueryData(String areaName,String begin, String end) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        CsyzVo csyzDto = new CsyzVo();
        csyzDto.setBeginTime(sdf.parse(begin));
        csyzDto.setEndTime(sdf.parse(end));
        List<CsyzVo> csyzVo = this.selectCsyzBackstage(csyzDto);
        List<CsyzVo> collect = csyzVo.stream().sorted(Comparator.comparing(CsyzVo::getTotal, Comparator.reverseOrder())).collect(Collectors.toList());
        for (int i=0; i<collect.size(); i++){
            CsyzVo dto = collect.get(i);
            if (dto.getAreaName().equals(areaName)){
                return i;
            }
        }
        return 1;
    }

    private List<OptDeviceAlarmDto> injectDispatchInfo(List<OptDeviceAlarmDto> list) {
        if (CollectionUtil.isNotEmpty(list)) {
            List<Long> ids = list.stream().map(OptDeviceAlarmDto::getId).distinct().collect(Collectors.toList());
            List<OptDeviceAlarmDto> list1 = baseMapper.recordListByIds(ids);
            Map<Long, OptDeviceAlarmDto> idMap = list1.stream().collect(Collectors.toMap(OptDeviceAlarmDto::getId, Function.identity()));
            for (OptDeviceAlarmDto optDeviceAlarmDto : list) {
                OptDeviceAlarmDto dto = idMap.get(optDeviceAlarmDto.getId());
                if(optDeviceAlarmDto.getConfigAlarmValue()!=null){
                    optDeviceAlarmDto.setConfigAlarmValue(BigDecimal.valueOf(optDeviceAlarmDto.getConfigAlarmValue()).setScale(2, RoundingMode.HALF_UP).doubleValue());
                }
                if(optDeviceAlarmDto.getConfigUpperLimit()!=null){
                    optDeviceAlarmDto.setConfigUpperLimit(BigDecimal.valueOf(optDeviceAlarmDto.getConfigUpperLimit()).setScale(2, RoundingMode.HALF_UP).doubleValue());
                }

                if (null != dto) {
                    optDeviceAlarmDto.setBusinessId(dto.getBusinessId());
                    optDeviceAlarmDto.setActivityName(dto.getActivityName());
                    optDeviceAlarmDto.setActivityFlag(dto.getActivityFlag());
                }
            }
        }
        return list;
    }
}
